import frappe
from frappe import _
from frappe.utils import flt, getdate, nowdate
from erpnext.manufacturing.doctype.bom.bom import BOM
from light_mes.light_mes.doctype.subcontracting_service_price.subcontracting_service_price import get_subcontracting_price
from light_mes.light_mes.doctype.operation_price_strategy.operation_price_strategy import get_operation_price

class CustomBOM(BOM):
    @frappe.whitelist()
    def get_routing(self):
        """重写获取工艺路线方法，增加自定义字段并计算委外单价"""
        if self.routing:
            self.set("operations", [])
            fields = [
                "sequence_id",
                "operation",
                "workstation",
                "workstation_type", 
                "description",
                "time_in_mins",
                "batch_size",
                "operating_cost",
                "idx",
                "hour_rate",
                "set_cost_based_on_bom_qty",
                "fixed_time",
                # 添加自定义字段
                "custom_is_subcontracting",
                "custom_enable_wip_receipt",
                "custom_supplier",
                "custom_rate_type"
            ]

            for row in frappe.get_all(
                "BOM Operation",
                fields=fields,
                filters={"parenttype": "Routing", "parent": self.routing},
                order_by="sequence_id, idx",
            ):
                child = self.append("operations", row)
                child.hour_rate = flt(row.hour_rate / self.conversion_rate, child.precision("hour_rate"))
            
            # 在获取完工艺路线后计算委外单价、获取税率、计算含税价
            self.calculate_operation_prices()
    
    def calculate_operation_prices(self):
        """为所有工序计算单价，根据不同的计价方式"""
        if not self.company or not self.item or not self.quantity:
            return
        
        # 获取Light Mes Settings 中设置的税率
        tax_rate = frappe.db.get_single_value("Light Mes Settings", "tax_rate") or 0
        tax_rate = flt(tax_rate)
        
        # 获取工序计价策略（按计价类型分组）
        price_strategies = self.get_operation_price_strategies()
        
        for operation in self.operations:
            # 根据计价类型计算单价
            rate_type = operation.custom_rate_type
            
            if not rate_type:
                continue
                
            price = 0
            
            if rate_type == "Subcontracting":
                # 如果是委外类型，使用原有的委外单价计算逻辑
                if operation.custom_supplier:
                    price = get_subcontracting_price(
                        company=self.company,
                        supplier=operation.custom_supplier,
                        qty=self.quantity,
                        item_code=self.item,
                        operation=operation.operation
                    )
            
            elif rate_type in ["By Hour", "By Qty"]:
                # 获取对应计价类型的所有策略（已按优先级排序）
                strategies = price_strategies.get(rate_type, [])
                
                # 按优先级遍历策略，直到找到价格
                for strategy in strategies:
                    # 根据策略获取价格
                    price = get_operation_price(
                        product=self.item,
                        strategy=strategy,
                        operation=operation,
                    )
                    
                    # 如果找到了价格，跳出循环
                    if price > 0:
                        break
            
            # 更新工序单价
            operation.custom_service_price = price
            # 如果单价大于0，计算含税价
            if price > 0 and rate_type == "By Qty":
                operation.custom_labour_cost = flt(price * self.quantity, operation.precision("custom_labour_cost"))
            elif price > 0 and rate_type == "By Hour":
                operation.custom_labour_cost = flt(price * operation.time_in_mins / 60, operation.precision("custom_labour_cost"))
            elif price > 0 and rate_type == "Subcontracting":
                operation.custom_tax_rate = tax_rate
                operation.custom_service_price_with_tax = flt(price * (1 + tax_rate / 100), operation.precision("custom_service_price_with_tax"))
                operation.custom_subcontracting_cost = flt(price * self.quantity, operation.precision("custom_subcontracting_cost"))
    
    def get_operation_price_strategies(self):
        """获取工序计价策略，按计价类型分组并按优先级排序"""
        strategies = {"By Hour": [], "By Qty": [], "Subcontracting": []}
        
        # 获取所有计价策略
        all_strategies = frappe.get_all(
            "Operation Price Strategy", 
            fields=["name", "rate_type", "price_doctype", "priority"],
            order_by="priority"  # 按优先级升序排列
        )
        
        # 按计价类型分组
        for strategy in all_strategies:
            rate_type = strategy.rate_type
            if rate_type in strategies:
                strategies[rate_type].append(strategy)
        
        return strategies
    